package com.vrp3d.security.realm;

import com.vrp3d.common.utils.JwtUtil;
import com.vrp3d.common.utils.ObjUtil;
import com.vrp3d.domain.po.User;
import com.vrp3d.security.token.JwtToken;
import com.vrp3d.service.UserService;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * token校验realm
 *
 * @author vrp3d
 */
@Slf4j
public class TokenValidateRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    /**
     * 调用{@code doGetAuthenticationInfo(AuthenticationToken)}之前会shiro会调用{@code supper.supports(AuthenticationToken)}
     * 来判断该realm是否支持对应类型的AuthenticationToken,如果相匹配则会走此realm
     *
     * @return
     */
    @Override
    public Class getAuthenticationTokenClass() {
        return JwtToken.class;
    }

    /**
     * 授权
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermission("sys:user:view");
        return info;
    }


    /**
     * 使用JwtToken登录的时候并未使用MD5加密，接下来会走到{ SimpleCredentialsMatcher}的{@code doCredentialsMatch}方法进行证书比对
     * 也就是此处传入的{@code Boolean.TRUE}与{@link JwtToken}中获取的证书相比较
     * 之所以不加密是因为无法获取用户加密前的密码，一旦经{ HashedCredentialsMatcher}进行证书比对则报错
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        JwtToken jwtToken = (JwtToken) token;
        String jwt = (String) jwtToken.getPrincipal();
        String username;
        try {
            Claims claims = JwtUtil.parseJwt(jwt);
            username = claims.get(JwtUtil.USERNAME).toString();
        } catch (AuthenticationException e) {
            throw new AuthenticationException();
        }
        User user = userService.findByMobile(username);
        if (ObjUtil.isEmpty(user)) {
            user = userService.findByEmail(username);
            /*if (ObjUtil.isEmpty(user)) {
                log.error("用户" + username + "不存在");
                throw new UserException(UserExceptionEnum.USER_DOES_NOT_EXIST);
            }*/
        }
        return new SimpleAuthenticationInfo(user, Boolean.TRUE, getName());
    }

}